﻿using System;
using Microsoft.Practices.Unity;
using TestByWire.AttributeHandlers;

namespace TestByWire
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
    public sealed class UseAdditionalTestTargetAttribute : Attribute, IContainerInteraction
    {
        public Type InterfaceType { get; private set; }
        public Type ImplementationType { get; private set; }

        public UseAdditionalTestTargetAttribute(Type interfaceType, Type implementationType)
        {
            if (interfaceType == null)
            {
                throw new ArgumentNullException("interfaceType");
            }

            if (implementationType == null)
            {
                throw new ArgumentNullException("implementationType");
            }

            if (!interfaceType.IsAssignableFrom(implementationType))
            {
                throw new InvalidOperationException("Interface type must be assignable from implementation type.");
            }

            InterfaceType = interfaceType;
            ImplementationType = implementationType;
        }

        Type IContainerInteraction.RegistrationType
        {
            get { return InterfaceType; }
        }

        string IContainerInteraction.RegistrationName
        {
            get { return null; }
        }

        public void Execute(IBuildContext buildContext)
        {
            if (buildContext.TestTarget != null)
                return;

            String name = null;
            IUnityContainer container = buildContext.Container;
            container.RegisterType(InterfaceType, ImplementationType, name);

            var settings = container.Resolve<PipelineSettings>();
            settings.DoNotStubList.Add(new DoNotStub(InterfaceType, name));
        }
    }
}